﻿#include "framework.h"
#include <CommCtrl.h>
#include <commdlg.h>
#include "MainWindow.h"
#include "Resource.h"

// 函数声明
static void MainWindow_Delete(MainWindow*);
static void MainWindow_DoModal(MainWindow*);
static void MainWindow_OnGameOver(MainWindow*);
static void MainWindow_OnMenuItemSetBorderClicked(MainWindow*, UINT);
static void MainWindow_OnMenuItemSetDifficultyClicked(MainWindow*, UINT);
static void MainWindow_OnMenuItemSetPictureClicked(MainWindow*);
static void MainWindow_OnMenuItemStartClicked(MainWindow*);
static void MainWindow_OnPictureCtrlClicked(MainWindow*, UINT);
static INT_PTR CALLBACK MainWindow_Proc(HWND, UINT, WPARAM, LPARAM);

/**
 * 创建主窗口。
 * @return 主窗口
 */
MainWindow* New_MainWindow() {
    MainWindow* mainWindow = (MainWindow*)calloc(1, sizeof(MainWindow));

    // 初始化数据
    mainWindow->mHandle = CreateDialog(NULL, MAKEINTRESOURCE(IDD_MAIN_WINDOW), NULL, MainWindow_Proc);
    SetWindowLongPtr(mainWindow->mHandle, GWLP_USERDATA, (LONG_PTR)mainWindow);

    // 初始化函数
    mainWindow->doModal = MainWindow_DoModal;

    // 设置菜单项
    CheckMenuRadioItem(GetMenu(mainWindow->mHandle), IDC_MENU_ITEM_EASY, 
        IDC_MENU_ITEM_HARD, IDC_MENU_ITEM_EASY, MF_CHECKED | MF_BYCOMMAND);
    CheckMenuRadioItem(GetMenu(mainWindow->mHandle), IDC_MENU_ITEM_HAS_BORDER, 
        IDC_MENU_ITEM_NO_BORDER, IDC_MENU_ITEM_HAS_BORDER, MF_CHECKED | MF_BYCOMMAND);

    // 创建游戏区域
    mainWindow->mGameBoard = New_GameBoard(mainWindow->mHandle, GAME_BOARD_X, GAME_BOARD_Y, GAME_BOARD_WIDTH, GAME_BOARD_HEIGHT);

    // 创建游戏
    mainWindow->mGame = New_Game(mainWindow->mHandle, mainWindow->mGameBoard->mDrawer, mainWindow->mGameBoard->mHandle);

    return mainWindow;
}

/**
 * 删除主窗口。
 * @param mainWindow    主窗口
 */
static void MainWindow_Delete(MainWindow* mainWindow) {
    // 删除游戏
    mainWindow->mGame->deleteSelf(mainWindow->mGame);

    // 删除游戏区域
    mainWindow->mGameBoard->deleteSelf(mainWindow->mGameBoard);

    // 销毁窗口
    DestroyWindow(mainWindow->mHandle);
    free(mainWindow);
}

/**
 * 以模态显示窗口。
 * @param mainWindow    主窗口
 */
static void MainWindow_DoModal(MainWindow* mainWindow) {
    MSG msg = { 0 };

    // 显示窗口
    ShowWindow(mainWindow->mHandle, SW_SHOW);

    // 窗口事件循环
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

/**
 * 游戏结束事件的响应函数。
 * @param mainWindow    主窗口
 */
static void MainWindow_OnGameOver(MainWindow* mainWindow) {
    TCHAR text[STRING_BUF_LEN] = { 0 };

    // 显示胜利提示信息
    LoadString(NULL, IDS_WON, text, STRING_BUF_LEN);
    MessageBox(mainWindow->mHandle, text, _T(" "), MB_ICONINFORMATION);
}

/**
 * "图片边框"菜单项的单击响应函数。
 * @param mainWindow    主窗口
 * @param id            菜单项 id
 */
static void MainWindow_OnMenuItemSetBorderClicked(MainWindow* mainWindow, UINT id) {
    // 如果要设置的参数与当前游戏参数相同，则直接返回
    BOOL hasBorder = id == IDC_MENU_ITEM_HAS_BORDER;
    if (hasBorder == mainWindow->mGame->mPicHasBorder) {
        return;
    }

    // 设置边框
    mainWindow->mGame->setPictureBorder(mainWindow->mGame, hasBorder);

    // 选中菜单项
    CheckMenuRadioItem(GetMenu(mainWindow->mHandle), IDC_MENU_ITEM_HAS_BORDER, IDC_MENU_ITEM_NO_BORDER, id, MF_BYCOMMAND);
}

/**
 * "难度"菜单项的单击响应函数。
 * @param mainWindow    主窗口
 * @param id            菜单项 id
 */
static void MainWindow_OnMenuItemSetDifficultyClicked(MainWindow* mainWindow, UINT id) {
    int clickedButton = 0;
    TCHAR text[STRING_BUF_LEN] = { 0 };
    GameDifficulty newDiff = EASY;

    // 如果要设置的参数与当前游戏参数相同，则直接返回
    switch (id) {
        case IDC_MENU_ITEM_HARD:
            newDiff = HARD;
            break;
        case IDC_MENU_ITEM_MEDIUM:
            newDiff = MEDIUM;
            break;
    }
    if (newDiff == mainWindow->mGame->mDifficulty) {
        return;
    }

    // 弹出询问对话框
    if (mainWindow->mGame->mStatus != END) {
        LoadString(NULL, IDS_RESET, text, STRING_BUF_LEN);
        clickedButton = MessageBox(mainWindow->mHandle, text, _T(" "), MB_ICONQUESTION | MB_YESNO);
        if (clickedButton == IDNO) {
            return;
        }
    }

    // 设置难度
    mainWindow->mGame->setDifficulty(mainWindow->mGame, newDiff);

    // 选中菜单项
    CheckMenuRadioItem(GetMenu(mainWindow->mHandle), IDC_MENU_ITEM_EASY, IDC_MENU_ITEM_HARD, id, MF_CHECKED);
}

/**
 * "换图片"菜单项的单击响应函数。
 * @param mainWindow    主窗口
 */
static void MainWindow_OnMenuItemSetPictureClicked(MainWindow* mainWindow) {
    TCHAR filter[] = _T("(*.bmp)\0*.bmp\0\0");
    TCHAR text[STRING_BUF_LEN] = { 0 };
    static TCHAR filePath[MAX_PATH] = { 0 };
    int clickedButton = 0;
    OPENFILENAME ofn = { sizeof(OPENFILENAME) };
    HBITMAP bitmap = NULL;

    // 弹出询问对话框
    if (mainWindow->mGame->mStatus != END) {
        LoadString(NULL, IDS_RESET, text, STRING_BUF_LEN);
        clickedButton = MessageBox(mainWindow->mHandle, text, _T(" "), MB_ICONQUESTION | MB_YESNO);
        if (clickedButton == IDNO) {
            return;
        }
    }

    // 弹出选择图片对话框
    ofn.hwndOwner = mainWindow->mHandle;
    ofn.lpstrFilter = filter;
    ofn.lpstrFile = filePath;
    ofn.nMaxFile = MAX_PATH;
    ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
    clickedButton = GetOpenFileName(&ofn);
    if (clickedButton == IDCANCEL) {
        return;
    }

    // 设置图片
    bitmap = LoadImage(NULL, filePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    mainWindow->mGame->setPicture(mainWindow->mGame, bitmap);
}

/**
 * "开始"菜单项的单击响应函数。
 * @param mainWindow    主窗口
 */
static void MainWindow_OnMenuItemStartClicked(MainWindow* mainWindow) {
    mainWindow->mGame->start(mainWindow->mGame);
}

/**
 * 图片控件的单击响应函数。
 * @param mainWindow    主窗口
 * @param id            用户单击的图片控件的 id
 */
static void MainWindow_OnPictureCtrlClicked(MainWindow* mainWindow, UINT id) {
    mainWindow->mGame->movePicture(mainWindow->mGame, id);
}

/**
 * 窗口过程函数。
 * @param window    窗口
 * @param message   事件标识
 * @param wParam    事件相关信息1
 * @param lParam    事件相关信息2
 * @return 事件在此被处理则返回 TRUE，否则返回 FALSE
 */
static INT_PTR CALLBACK MainWindow_Proc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) {
    MainWindow* mainWindow = (MainWindow*)GetWindowLongPtr(window, GWLP_USERDATA);
    WORD id = LOWORD(wParam);
    UNREFERENCED_PARAMETER(lParam);

    switch (message) {
        case UM_GAME_OVER:
            MainWindow_OnGameOver(mainWindow);
            return TRUE;
        case WM_COMMAND:
            if (id >= IDC_PICTURE_CTRL && id <= IDC_PICTURE_CTRL + MAX_PICTURE_CTRL_COUNT) {
                MainWindow_OnPictureCtrlClicked(mainWindow, id);
                return TRUE;
            }
            switch (id) {
                case IDC_MENU_ITEM_START:
                    MainWindow_OnMenuItemStartClicked(mainWindow);
                    return TRUE;
                case IDC_MENU_ITEM_EASY:
                case IDC_MENU_ITEM_HARD:
                case IDC_MENU_ITEM_MEDIUM:
                    MainWindow_OnMenuItemSetDifficultyClicked(mainWindow, id);
                    return TRUE;
                case IDC_MENU_ITEM_HAS_BORDER:
                case IDC_MENU_ITEM_NO_BORDER:
                    MainWindow_OnMenuItemSetBorderClicked(mainWindow, id);
                    return TRUE;
                case IDC_MENU_ITEM_SET_PICTURE:
                    MainWindow_OnMenuItemSetPictureClicked(mainWindow);
                    return TRUE;
                case IDCANCEL:
                    MainWindow_Delete(mainWindow);
                    return TRUE;
            }
            return TRUE;
        case WM_DESTROY:
            PostQuitMessage(0);
            return TRUE;
    }
    return FALSE;
}
